#pragma once

#include <MyFC/GridControl.h>

#include "TreeControl.h"
#include "Timeline.h"

namespace My {

class Xline;

class DLL_API XlineHeader : 
	public virtual Control, 
	private Container 
{
	friend class XlineBox;
public:
	XlineHeader(Xline &);
public:
	My::Size GetHeaderHeight() const;
public:
	virtual CRect Bounds() const;
	virtual void LayoutControls();
	virtual void HandlePaint(CDC *, const CRect &);
private:
	void PaintCell(CDC *, const CRect & rClip, const Column &, const CRect & rCell);
private:
	Xline &	m_Xline;
};

class DLL_API XlineGrid : public Tree, public Grid 
{
	friend class XlineBox;
private:
	class RubberRect {
	public:
		RubberRect(XlineGrid &);
		void PinDown(CPoint);
		void Stretch(CPoint);
		void SetVisible(bool);
		CRect GetBox();
		void Draw(CDC * pDC);
		bool IsVisible() const 
			{ return m_Visible; };
	private:
		void Show();
		void Hide();
	private:
		XlineGrid &		m_Grid;
		bool			m_Visible;
		bool			m_Shown;
		CRect			m_Box;
		CRect			m_Rect;
	};
public:
	XlineGrid(Xline &);
public:
	void ShowInsertion(bool on, My::Size iRow = My::Size(-1));
public:
	virtual CRect Bounds() const;
	virtual void HandleLeftDown(unsigned int, const CPoint &);
	virtual void HandleLeftUp(unsigned int, const CPoint &);
	virtual bool HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p);
	virtual void HandleDragging(unsigned int, const CPoint &);
	virtual void HandleDragEnd(unsigned int, const CPoint &);
	virtual void HandlePaint(CDC *, const CRect &);
	virtual void UpdateBounds();
	virtual void ProcessEvent(Event &);
	virtual const CFont * Font() const
		{ return &m_SmallFont; }
protected:
	virtual void Paint(CDC *, const CRect &);
	virtual void UpdateContentSize();
private:
	void PaintTimeColumn(CDC *, const CRect &);
	void UpdateDotLine();
	void DrawInsertion(CDC * = 0);
private:
	Xline &			m_Xline;
	RubberRect		m_RubberRect;
	int				m_DotLineX;
	bool			m_DotLineVisible;
	CFont			m_SmallFont;
	bool			m_InsertionVisible;
	int				m_InsertionRow;
	int				m_InsertionY;
};

class DLL_API XlineBox : public ScrollBox 
{
	friend class Xline;
	friend class XlineHeader;
	friend class XlineGrid;
public:
	XlineBox(Xline &);
public:
	virtual CRect Bounds() const;
protected:
	virtual void UpdateBounds();
private:
	Xline &		m_Xline;
	XlineHeader	m_Header;
	XlineGrid	m_Grid;
};

class DLL_API XlineCol : public Column {
	friend class Xline;
public:
	using Column::SetWidth;
	using Column::SetVisible;
	void SetCaption(const String & s)
		{ m_Caption = s; }
	virtual String GetCaption() const
		{ return m_Caption; }
private:
	String	m_Caption;
};

class DLL_API Xline : public Timeline
{
	friend class XlineHeader;
	friend class XlineGrid;
	friend class XlineBox;
public:
	Xline();
	~Xline();
public:
	const XlineCol & GetNameCol() const
		{ return m_NameCol; }
	XlineCol & GetNameCol()
		{ return m_NameCol; }
	const XlineCol & GetTimeCol() const
		{ return m_TimeCol; }
	XlineCol & GetTimeCol()
		{ return m_TimeCol; }
public:
	virtual CSize GetPreferredSize() const;
	virtual void LayoutControls();
	virtual void RangeSelect(const rect<int> &) { }
public:
	XlineBox & GetBox()
		{ return m_Box; }
	XlineGrid & GetGrid()
		{ return m_Box.m_Grid; }
	XlineHeader & GetHeader()
		{return m_Box.m_Header; }
	virtual void UpdateBounds();
protected:
	XlineBox	m_Box;
	XlineCol	m_NameCol;
	XlineCol	m_TimeCol;
};

} // My
